<?php
/**
 * @purpose
 * @Author: Madou
 * @Time  : 2022/8/6 14:13
 */

namespace App\Trip\Train\Order\Impl;

use App\Models\Task\SnapTasks\Repositories\SnapTaskTrip;
use App\Models\Task\SnapTasks\SnapTask;
use App\Models\Train\TrainOrderPassengers\TrainOrderPassenger;
use App\Models\Train\TrainOrders\Repositories\Interfaces\TrainOrdersRepositoryInterface;
use App\Models\Train\TrainOrders\TrainOrder;
use App\Models\Train\TrainOrderTrain\TrainOrderTrain;
use App\Trip\Code;
use App\Trip\Orders\BookOrders\Train\SelectedSeats\ParseOrderSelectedSeats;
use App\Trip\Train\Order\Interfaces\TrainBookInterface;
use App\Trip\Train\Providers\PiaoChi\Passenger\CardType;
use App\Trip\Train\Providers\PiaoChi\Passenger\PassengerType;
use App\Trip\Train\Providers\PiaoChi\TrainOrderService;
use Exception;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;

class PiaoChiTrainBookForSnapImpl implements TrainBookInterface
{
    private TrainOrderService $order_service;
    private TrainOrder        $order;
    private SnapTask          $task;
    private SnapTaskTrip      $task_trip;

    public function __construct(SnapTask $task, TrainOrder $order, SnapTaskTrip $task_trip)
    {
        $this->task      = $task;
        $this->task_trip = $task_trip;
        $this->setTrainOrder($order);
        $this->setOrderService();
    }

    public function setTrainOrder(TrainOrder $order)
    {
        $this->order = $order;
    }

    public function setOrderService()
    {
        $this->order_service = new TrainOrderService();
    }

    /**
     * @throws Exception
     */
    public function book()
    {
        /**
         * @var TrainOrderTrain     $main_train
         * @var TrainOrderTrain     $origin_main_train
         * @var TrainOrder          $order
         * @var TrainOrder|null     $second_order 火车票中转第二行程
         * @var TrainOrderPassenger $passenger
         * @var int                 $type 业务类型:0为出票、1为退票、2为改签、3为打印凭证
         */
        $lock_cache_key = "Train:Order:book:{$this->order->getOrderSn()}";
        if (!Redis::set($lock_cache_key, 1, 'nx', 'ex', config('trip.ttl.minutes'))) {
            throw new Exception("当前不允许执行抢票操作,{$this->order->getOrderSn()}");
        }
        $trainOrderRepo = app(TrainOrdersRepositoryInterface::class);
        $trips          = [];
        $order          = $this->order;
        $trips[]        = $this->buildTrip($order);

        try {
            $book = $this->order_service->trainBook(['trip' => $trips, 'order_sn' => $order->getOutOrderSn()]);
        } catch (Exception $e) {
            Log::error("低速抢票订票失败:{$order->getOutOrderSn()},".$e->getMessage());
            throw new Exception("抢票订单订票失败", Code::TRAIN_ORDER_LOW_SNAP_BOOK_FAILED);
        }
        $res = json_encode($book, JSON_UNESCAPED_UNICODE);
        Log::info("Train:Order:book:order_sn:{$order->getOrderSn()},out_order_sn:{$order->getOutOrderSn()},{$res}");
        $trainOrderRepo->saveOutOrderId($order, $book['order_id']);
        return $book['order_id'];
    }

    /**
     * @throws Exception
     */
    private function buildTrip(TrainOrder $order): array
    {
        // 获取最新状态
        $order->refresh();
        if ($order->isCancel()) {
            throw new Exception("低速抢票订票异常拦截,订单已取消:{$order->getOrderSn()}");
        }

        if (!$this->order->isSnapUp()) {
            throw new Exception("低速抢票订票异常拦截,订单非抢票订单:{$order->getOrderSn()}");
        }


        if ($this->task->isPaidHighLevel()) {
            throw new Exception("低速抢票订票异常拦截,订单为高速付费抢票订单:{$order->getOrderSn()}");
        }


        /**
         * @var TrainOrderTrain     $main_train
         * @var TrainOrderPassenger $passenger
         */
        $date           = $this->task_trip->getDepartAt();
        $from_station   = $this->task_trip->getFromStationName();
        $to_station     = $this->task_trip->getToStationName();
        $train_code     = $this->task_trip->getTrainCode();
        $passengers     = $order->getPassengers();
        $selected_seats = $this->order->getSelectedSeats();
        // 目前info 信息主要填写选座信息
        $info = "";
        if ($selected_seats) {
            $selectSeat = new ParseOrderSelectedSeats($selected_seats);
            $info       = $selectSeat->getSelectedSeatRemark();
        }

        $trip_passengers = [];
        foreach ($passengers as $key => $passenger) {
            $trip_passengers[$key] = [
                "realname"         => $passenger->getTrueName(),
                "realcode"         => $passenger->getIdentityCode(),
                "realcode_guoji"   => "中华人民共和国",
                "cardtype"         => CardType::getCardType($passenger->getIdentityType()),
                "peopletype"       => PassengerType::getPeopleType($passenger->getPassengerType()),
                "seattip"          => $passenger->getSeatName(),
                "seatcodes"        => "",
                "email"            => "",
                "mobile"           => $passenger->getMobile(),
                "price"            => $passenger->getSeatPrice(),
                "paytype"          => $this->order_service::PAY_TYPE_ELECTRONIC,
                "info"             => $info,
                "type"             => $this->order_service::BOOK_TYPE_BOOK,
                "sub_passenger_id" => $passenger->subPassengerId(),
            ];
        }
        return [
            "type"        => $this->order_service::BUSINESS_TYPE_TICKET,
            "flytime"     => $date,
            "fromcity"    => $from_station,
            "tocity"      => $to_station,
            "carcode"     => $train_code,
            "info"        => $info,
            "passenger"   => $trip_passengers,
            "sub_trip_id" => $order->getOrderSn(), // 回调用于判别是哪笔订单
        ];
    }
}